♻️ Migrate Storybook & Static-Site SDKs from Puppeteer to Playwright#193
Conversation
Instead of doing full page.goto() for each story (which reloads the entire Storybook bundle), we now: 1. First story per tab: Full page load to initialize Storybook 2. Subsequent stories: Client-side navigation via __STORYBOOK_PREVIEW__ Performance improvement: ~47x faster (94s → 2s for 10 screenshots) Changes: - Add navigation.js with smart client-side routing - Sort tasks by viewport to minimize resize operations - Skip resetTab() to keep Storybook context loaded - Update task structure to use storyId/baseUrl instead of url - Fix example-storybook: add vite.config.js with React plugin
This comment has been minimized.
This comment has been minimized.
Code Review: Client-Side Navigation for Storybook ScreenshotsSummaryExcellent performance optimization achieving 47x speedup (94s → 2s). Well-architected with comprehensive test coverage and thoughtful error handling. Key Strengths
Critical Issues1. Memory Leak: Event Listener Cleanup (MUST FIX)Location: navigation.js:107-122 If storyRendered event fires before timeout, the timeout is NOT cleared. This creates timer leaks. Fix: Add clearTimeout when event handler fires: let timeoutId;
let handleRendered = () => {
clearTimeout(timeoutId);
preview.channel.off('storyRendered', handleRendered);
resolve();
};
timeoutId = setTimeout(() => { /* ... */ }, timeout);2. Hard-coded Timeout (SHOULD FIX)Location: navigation.js:118-122 5-second timeout is hard-coded, ignoring the configurable timeout parameter. Use the passed timeout instead of 5000ms. 3. Silent Error Swallowing (SHOULD FIX)Location: navigation.js:49-56 Catch block silently swallows errors. Add debug logging before fallback. Minor Issues
Security & Performance
VerdictApprove with changes ✅ Outstanding work with significant performance gains. Fix the timer leak (#1) and hard-coded timeout (#2) before merge. Once addressed, ready to ship. Performance: 🚀 47x faster | Quality: 📝 Well-tested | Risk: 🟢 Low |
Add backwards-compatible support for new `vizzlyPlugin` package.json field alongside legacy `vizzly.plugin`. This fixes cosmiconfig conflict where `vizzly` field was being read as config instead of plugin marker. - Plugin loader now checks `vizzlyPlugin` first, falls back to `vizzly.plugin` - Existing plugins continue to work unchanged
E2E tests now run the actual CLI commands like users would: - Storybook: `vizzly storybook ./example-storybook/dist` - Static-site: `vizzly static-site ../../test-site` Old SDK integration tests renamed to sdk-integration.test.js and moved to separate test:sdk-integration script. Added .vizzlyrc.js for local dev plugin loading, and updated both plugins to use new vizzlyPlugin field.
- Use Puppeteer browser caching instead of Playwright (both plugins use Puppeteer) - Add example-storybook build step before running E2E tests
Code review fixes: - Clear timeout when storyRendered event fires (prevents timer leak) - Use configurable timeout parameter instead of hardcoded 5000ms - Add debug logging before falling back to full page navigation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
The .vizzlyrc.js config loads plugins from ./dist/plugin.js, which requires building the client first.
Vizzly - Visual Test ResultsCLI Reporter - 6 changes need review
Changes needing review (6)filter-failed-only · Firefox · 1920×1080 · 1.3% diff bulk-accept-dialog · Firefox · 1920×1080 · 9.8% diff fullscreen-viewer · Firefox · 1920×1080 · 0.1% diff viewer-zoomed-100 · Firefox · 1920×1080 · 0.2% diff fullscreen-viewer · Firefox · 375×667 · 79.9% diff bulk-accept-dialog · Firefox · 375×667 · 159.2% diff CLI TUI - Processing...Build in progress...
|
Vizzly - Visual Test ResultsCLI Reporter - 6 changes need review
Changes needing review (6)filter-failed-only · Firefox · 1920×1080 · 1.3% diff bulk-accept-dialog · Firefox · 1920×1080 · 9.8% diff fullscreen-viewer · Firefox · 1920×1080 · 0.1% diff viewer-zoomed-100 · Firefox · 1920×1080 · 0.2% diff fullscreen-viewer · Firefox · 375×667 · 79.9% diff bulk-accept-dialog · Firefox · 375×667 · 159.2% diff CLI TUI - 1 change needs review
|
Adds detailed timing breakdowns when VIZZLY_LOG_LEVEL=debug: - Navigation: mode selection and duration for each story - Task steps: viewport, navigate, hook, screenshot timing - Screenshot: capture vs send timing breakdown - Client SDK: HTTP call duration - Server handlers: request received/returned timing Enabled verbose logging in CI for Storybook E2E tests.
Vizzly - Visual Test ResultsCLI Reporter - 6 changes need review
Changes needing review (6)filter-failed-only · Firefox · 1920×1080 · 1.3% diff fullscreen-viewer · Firefox · 1920×1080 · 0.1% diff bulk-accept-dialog · Firefox · 1920×1080 · 10.4% diff viewer-overlay-mode · Firefox · 1920×1080 · 0.7% diff viewer-zoomed-100 · Firefox · 1920×1080 · 0.2% diff bulk-accept-dialog · Firefox · 375×667 · 159.2% diff CLI TUI - 1 change needs review
|
- Add 45s timeout to screenshot capture to fail fast on hangs - Auto-detect concurrency from CPU cores (half cores, min 2, max 8) - Aligns with static-site SDK behavior
Vizzly - Visual Test ResultsCLI Reporter - 7 changes need review
Changes needing review (7)viewer-zoomed-100 · Firefox · 1920×1080 · 0.2% diff fullscreen-viewer · Firefox · 1920×1080 · 1.6% diff fullscreen-viewer · Firefox · 375×667 · 167.4% diff viewer-slide-mode · Firefox · 1920×1080 · 0.6% diff viewer-toggle-mode · Firefox · 1920×1080 · 0.1% diff bulk-accept-dialog · Firefox · 375×667 · 159.0% diff ...and 1 more in Vizzly. CLI TUI - 1 change needs review
|
- Remove --disable-gpu (not needed since 2021) - Remove --disable-software-rasterizer (caused hangs with disable-gpu) - Remove --disable-translate (removed April 2017) - Remove --safebrowsing-disable-auto-update (removed Nov 2017) - Add --disable-features=Translate,OptimizationHints,MediaRouter - Add --hide-scrollbars, --mute-audio, --force-color-profile=srgb - Add docs/browser-flags.md documenting all flags and source of truth
Vizzly - Visual Test ResultsCLI Reporter - 6 changes need review
Changes needing review (6)fullscreen-viewer · Firefox · 375×667 · 10.3% diff filter-failed-only · Firefox · 1920×1080 · 1.3% diff bulk-accept-dialog · Firefox · 1920×1080 · 10.3% diff viewer-slide-mode · Firefox · 1920×1080 · 0.5% diff viewer-zoomed-100 · Firefox · 1920×1080 · 0.2% diff bulk-accept-dialog · Firefox · 375×892 · 95.5% diff CLI TUI - 1 change needs review
|
Puppeteer's new headless mode has known issues with parallel screenshot capture causing timeouts. Playwright is designed for automation and handles parallel contexts properly. Changes: - Replace puppeteer with playwright-core - Use BrowserContext for isolation instead of tabs - Update page.evaluate() syntax for Playwright - Use page.setViewportSize() instead of page.setViewport() - Use waitUntil: 'networkidle' instead of 'networkidle2' - Update CI workflow to install Playwright browsers
Vizzly - Visual Test ResultsCLI Reporter - 6 changes need review
Changes needing review (6)filter-failed-only · Firefox · 1920×1080 · 1.3% diff fullscreen-viewer · Firefox · 1920×1080 · 0.1% diff bulk-accept-dialog · Firefox · 1920×1080 · 6.8% diff viewer-zoomed-100 · Firefox · 1920×1080 · 0.2% diff fullscreen-viewer · Firefox · 375×667 · 198.0% diff bulk-accept-dialog · Firefox · 375×667 · 159.1% diff CLI TUI - 1 change needs review
|
Same migration as Storybook SDK for consistency and performance. Screenshots now complete in ~1s instead of 2+ minutes. Changes: - Replace puppeteer with playwright-core - Use BrowserContext for isolation instead of CDP sessions - Use page.setViewportSize() instead of page.setViewport() - Update CI workflow to install Playwright browsers
Vizzly - Visual Test ResultsCLI Reporter - 6 changes need review
Changes needing review (6)fullscreen-viewer · Firefox · 375×667 · 78.6% diff bulk-accept-dialog · Firefox · 1920×1080 · 6.8% diff viewer-zoomed-100 · Firefox · 1920×1080 · 0.4% diff fullscreen-viewer · Firefox · 1920×1080 · 1.4% diff viewer-overlay-mode · Firefox · 1920×1080 · 5.9% diff viewer-toggle-mode · Firefox · 1920×1080 · 0.1% diff CLI TUI - 1 change needs review
|
- Update pool tests to use BrowserContext mocks (newContext instead of newPage) - Update viewport tests to use setViewportSize (Playwright API) - Update navigation tests to use networkidle (not networkidle2) - Update screenshot tests to include timeout parameter - Fix lint formatting issues
Vizzly - Visual Test Results
|










































Summary
This PR fixes critical screenshot timeout issues in CI and dramatically improves performance by migrating both the Storybook and Static-Site SDKs from Puppeteer to Playwright.
Root cause: Puppeteer's new headless mode has known issues with parallel screenshot capture causing timeouts. Playwright's BrowserContext provides proper isolation for parallel workers.
Results:
Changes
Puppeteer → Playwright Migration
puppeteerwithplaywright-corein both SDKssetViewport()→setViewportSize(),networkidle2→networkidlepage.evaluate()syntax: Playwright uses object destructuring({ args }) => {}, { args }Chrome Browser Flags Audit
--disable-gpu+--disable-software-rasterizer)--disable-translate,--safebrowsing-disable-auto-update)--disable-features=Translate,OptimizationHints,MediaRouterapproach--force-color-profile=srgb,--hide-scrollbars)docs/browser-flags.mdwith source of truth referencesStorybook Client-Side Navigation
__STORYBOOK_PREVIEW__.channel.emit('setCurrentStory')instead of full page reloadsstoryRenderedeventPlugin System Enhancement
vizzlyPluginfield in package.json for plugin registrationCI Improvements
Test plan